﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace SSPharma.Utility.Filter
{

    public enum FilterOption
    {
        EQ,
        NOT_EQ,
        GT,
        GT_OR_EQ,
        LT,
        LT_OR_EQ,
        BEGIN,
        NOT_BEGIN,
        END,
        NOT_END,
        CONTAIN,
        NOT_CONTAIN
    }

    public enum LinkOption
    {
        OR,
        AND,
    }

    public class CustomFilter<T> : FilterBase where T : IComparable
    {
        #region Variables

        private PropertyInfo _propertyInfo;

        private T _firstFilterValue;
        private FilterOption _firstFilterOption;

        private T _secondFilterValue;
        private FilterOption _secondFilterOption;

        private LinkOption _filterLinkOption;

        #endregion

        #region Constructor

        public CustomFilter(PropertyInfo propertyInfo)
        {
            _propertyInfo = propertyInfo;
        }

        #endregion

        #region Properties

        public T FirstFilterValue
        {
            get { return _firstFilterValue; }
            set
            {
                _firstFilterValue = value;
                OnFilterChanged();
            }
        }

        public FilterOption FirstFilterOption
        {
            get { return _firstFilterOption; }
            set
            {
                _firstFilterOption = value;
                OnFilterChanged();
            }
        }

        public T SecondFilterValue
        {
            get { return _secondFilterValue; }
            set
            {
                _secondFilterValue = value;
                OnFilterChanged();
            }
        }

        public FilterOption SecondFilterOption
        {
            get { return _secondFilterOption; }
            set
            {
                _secondFilterOption = value;
                OnFilterChanged();
            }
        }

        public LinkOption LinkOption
        {
            get { return _filterLinkOption; }
            set
            {
                _filterLinkOption = value;
                OnFilterChanged();
            }
        }

        #endregion

        #region public methods

        public override bool IsMatch(object target)
        {
            if (target == null)
            {
                return false;
            }

            T value = (T)_propertyInfo.GetValue(target, null);

            if (_filterLinkOption == LinkOption.AND)
            {
                return CheckFirstFilterValue(_firstFilterValue, value, _firstFilterOption) &&
                       CheckFirstFilterValue(_secondFilterValue, value, _secondFilterOption);
            }
            else
            {
                return CheckFirstFilterValue(_firstFilterValue, value, _firstFilterOption) ||
                       CheckFirstFilterValue(_secondFilterValue, value, _secondFilterOption);
            }
        }

        #endregion

        #region private methods

        private bool CheckFirstFilterValue(T filterValue, T value, FilterOption option)
        {
            switch (option)
            {
                case FilterOption.EQ:
                    return value.CompareTo(filterValue) == 0;
                case FilterOption.NOT_EQ:
                    return value.CompareTo(filterValue) != 0;
                case FilterOption.GT:
                    return value.CompareTo(filterValue) > 0;
                case FilterOption.GT_OR_EQ:
                    return value.CompareTo(filterValue) >= 0;
                case FilterOption.LT:
                    return value.CompareTo(filterValue) < 0;
                case FilterOption.LT_OR_EQ:
                    return value.CompareTo(filterValue) <= 0;
                case FilterOption.BEGIN:
                    return value.ToString().StartsWith(filterValue.ToString(), StringComparison.OrdinalIgnoreCase);
                case FilterOption.NOT_BEGIN:
                    return !(value.ToString().StartsWith(filterValue.ToString(), StringComparison.OrdinalIgnoreCase));
                case FilterOption.END:
                    return value.ToString().EndsWith(filterValue.ToString(), StringComparison.OrdinalIgnoreCase);
                case FilterOption.NOT_END:
                    return !(value.ToString().EndsWith(filterValue.ToString(), StringComparison.OrdinalIgnoreCase));
                case FilterOption.CONTAIN:
                    return value.ToString().Contains(filterValue.ToString());
                case FilterOption.NOT_CONTAIN:
                    return !(value.ToString().Contains(filterValue.ToString()));
                default:
                    return true;
            }
        }

        #endregion

    }

}
